import Router from 'koa-router';
import { SysUserService } from '../../service/system/SysUser.js';
import {
  CreateSysUserDto,
  UpdateSysUserDto,
  SysUserQueryDto,
} from '../../entities/system/SysUser.js';
import type { AppContext } from '../../types/index.js';
import { Response } from '../../utils/response.js';
import { BusinessException } from '../../types/exceptions.js';
import { ValidationUtil } from '../../utils/validation.js';

const router = new Router<Record<string, unknown>, AppContext>();

/**
 * 用户控制器
 * @description 使用单例模式，避免重复创建服务实例
 */
class UserController {
  private static instance: UserController;
  private readonly userService: SysUserService;

  private constructor() {
    this.userService = new SysUserService();
  }

  static getInstance(): UserController {
    if (!UserController.instance) {
      UserController.instance = new UserController();
    }
    return UserController.instance;
  }

  /**
   * 创建用户
   * @description 创建新的系统用户
   */
  async create(ctx: AppContext): Promise<void> {
    const user = ctx.request.body as CreateSysUserDto;

    // 参数验证
    ValidationUtil.validateRequiredString(user.user_name as string, '用户名');
    ValidationUtil.validateRequiredString(user.nick_name as string, '昵称');

    // 检查用户名是否已存在
    const existingUser = await this.userService.loadUser(user.user_name as string);
    if (existingUser) {
      throw new BusinessException('用户名已存在');
    }

    // 如果提供了手机号，检查手机号是否已存在
    if (user.mobile) {
      const existingMobile = await this.userService.loadUserByMobile(user.mobile as string);
      if (existingMobile) {
        throw new BusinessException('手机号已被使用');
      }
    }

    const userId = await this.userService.create(user);
    ctx.body = Response.success('创建成功', { id: userId });
  }

  /**
   * 获取用户列表
   * @description 分页获取系统用户列表，支持多种查询条件
   */
  async list(ctx: AppContext): Promise<void> {
    const { page, pageSize, ...query } = ctx.query;
    const { pageNum, pageSizeNum } = ValidationUtil.validatePagination(
      page as string,
      pageSize as string
    );

    const result = await this.userService.list(pageNum, pageSizeNum, query as SysUserQueryDto);
    ctx.body = Response.pagination('查询成功', result);
  }

  /**
   * 更新用户信息
   * @description 根据用户ID更新用户信息
   */
  async update(ctx: AppContext): Promise<void> {
    const id = ValidationUtil.validateId(ctx.params.id, '用户ID');
    const user = ctx.request.body as UpdateSysUserDto;

    // 参数验证
    if (user.user_name) {
      ValidationUtil.validateRequiredString(user.user_name as string, '用户名');

      // 检查用户名是否已被其他用户使用
      const existingUser = await this.userService.loadUser(user.user_name as string);
      if (existingUser && existingUser.id !== id) {
        throw new BusinessException('用户名已存在');
      }
    }

    if (user.nick_name) {
      ValidationUtil.validateRequiredString(user.nick_name as string, '昵称');
    }

    // 如果更新手机号，检查是否已被其他用户使用
    if (user.mobile) {
      const existingMobile = await this.userService.loadUserByMobile(user.mobile as string);
      if (existingMobile && existingMobile.id !== id) {
        throw new BusinessException('手机号已被使用');
      }
    }

    const success = await this.userService.update(id, user);
    if (!success) {
      throw new BusinessException('用户不存在或已被删除');
    }

    ctx.body = Response.success('更新成功');
  }

  /**
   * 删除用户
   * @description 根据用户ID删除用户（软删除）
   */
  async delete(ctx: AppContext): Promise<void> {
    const id = ValidationUtil.validateId(ctx.params.id, '用户ID');

    const success = await this.userService.delete(id);
    if (!success) {
      throw new BusinessException('用户不存在');
    }

    ctx.body = Response.success('删除成功');
  }

  /**
   * 获取用户详情
   * @description 根据用户ID获取用户详细信息
   */
  async getById(ctx: AppContext): Promise<void> {
    const id = ValidationUtil.validateId(ctx.params.id, '用户ID');

    const user = await this.userService.getById(id);
    if (!user) {
      throw new BusinessException('用户不存在');
    }
    ctx.body = Response.success('获取成功', user);
  }
}

const controller = UserController.getInstance();

/**
 * 路由定义 - 使用控制器方法
 */
router.post('/create', (ctx: AppContext) => controller.create(ctx));
router.get('/list', (ctx: AppContext) => controller.list(ctx));
router.put('/:id', (ctx: AppContext) => controller.update(ctx));
router.delete('/:id', (ctx: AppContext) => controller.delete(ctx));
router.get('/:id', (ctx: AppContext) => controller.getById(ctx));

export default router;
